package org.bing.engine.common.store;

import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;

import org.bing.engine.common.logging.Log;
import org.bing.engine.common.logging.LogFactory;
import org.bing.engine.utility.codec.PrimitiveJsonCodec;
import org.bing.engine.utility.helper.FileHelper;
import org.bing.engine.utility.helper.StringHelper;

public class SimpleLocalStore {
    private static final Log logger = LogFactory.getLog(SimpleLocalStore.class);
    private PrimitiveJsonCodec jsonCodec = new PrimitiveJsonCodec();
    private boolean flag = true;
    private String location;

    public void setLocation(String loc) {
        this.location = loc;
    }

    public void init() {
        if (flag) {
            flag = false;
            location = fixStorePath(location);
            File file = new File(location);
            if (file.isDirectory()) {
                logger.error("Store file:" + location + " is directory, remove it first!");
                throw new RuntimeException("Store file " + location + " is directory!");
            } else {
                if (!file.exists()) {
                    file.getParentFile().mkdirs();
                    try {
                        file.createNewFile();
                    } catch (IOException e) {
                        logger.error("Can't create file:" + location, e);
                    }
                }
            }
            logger.info("Simple store location: " + location);
        }
    }

    public void save(String key, String value) {
        Properties p = new Properties();
        FileInputStream fis = null;
        FileOutputStream fos = null;
        try {
            fis = new FileInputStream(location);
            p.load(fis);
            p.setProperty(key, value);
            fos = new FileOutputStream(location);
            p.store(fos, "simple store, agile.chen@gmail.com");
        } catch (IOException e) {
            logger.error("Fail to store file:" + location, e);
            throw new RuntimeException(e);
        } finally {
            close(fis);
            close(fos);
        }
    }

    public void saveForObject(String key, Object obj) {
        String value = jsonCodec.encode(obj);
        this.save(key, value);
    }

    public String query(String key) {
        Properties p = new Properties();
        FileInputStream fis = null;
        try {
            fis = new FileInputStream(location);
            p.load(fis);
            return p.getProperty(key);
        } catch (IOException e) {
            logger.error("Fail to query " + key + " in file " + location, e);
            throw new RuntimeException(e);
        } finally {
            close(fis);
        }
    }

    public Object queryForObject(String key) {
        String value = this.query(key);
        return jsonCodec.decode(value);
    }

    private void close(Closeable cls) {
        if (cls != null) {
            try {
                cls.close();
            } catch (IOException e) {
                logger.error("Fail to close " + cls);
                cls = null;
            }
        }
    }

    private String fixStorePath(String path) {
        String property = StringHelper.getProperty(path);
        while (property != null) {
            String value = System.getenv(property);
            if (StringHelper.isBlank(value)) {
                value = System.getProperty(property);
                if (StringHelper.isBlank(value)) {
                    throw new RuntimeException("Can't find env_var or property: " + property);
                }
            }
            path = StringHelper.replaceWithProperty(path, property, value);
            property = StringHelper.getProperty(path);
        }
        return FileHelper.fixPathToNative(path);
    }

    public static void main(String[] args) {
        System.out.println(System.getenv("JAVA_HOME"));
        System.out.println(System.getProperty("JAVA_HOME"));
    }

}
